from celery import shared_task
from django.utils import timezone
from django.db import transaction
from django.db.models import Avg, Max, Min, Count, Sum
from mysqldb.models import *
import hashlib, math


def hasHashCode(i, t):
    """计算hash值"""
    m = hashlib.md5()
    m.update((i * t).encode("utf-8"))
    return m.hexdigest()


def validate_Hash(i, h, d):
    """校验hash"""
    if not i:
        return True
    return h == hasHashCode(i, d.strftime("%Y-%m-%d"))


@shared_task
def ConvertInterManual(*args, **kwargs):
    """手动兑换积分"""
    # print(args, kwargs)
    # print(timezone.now())
    assert kwargs["intertype"] != 1, "积分类型异常"

    # 检查兑换比例
    try:
        r = AllinpayPlaceinterConf.objects.get(
            pid=kwargs["pid"], intetype=kwargs["intertype"]
        )
    except BaseException as err:
        assert False, "该类积分不允许兑换"
    else:
        assert r.scale, "兑换比例设置错误"
        assert kwargs["money"] >= r.mixamount, "未达到最小兑换金额"

    # 检查经营账户
    try:
        b = AllinpayPlacebankList.objects.get(pid=kwargs["pid"])
    except BaseException as err:
        AllinpayPlacebankList(
            pid=kwargs["pid"], money=0, status=1, currentime=timezone.now()
        ).save()
        assert False, "场所经营账户余额不足"
    else:
        assert b.status, "场所经营账户停用"

    assert kwargs["money"] <= b.money, "场所经营账户余额不足"
    assert validate_Hash(b.money, b.hash, b.currentime.date()), "场所经营账户余额校验失败，请联系管理员"

    # 检查个人账户
    try:
        s = AllinpayPlaceinterList.objects.get(
            pid=kwargs["pid"], sid=kwargs["sid"], intertype=kwargs["intertype"]
        )
    except BaseException as err:
        assert False, "积分余额不足"
    else:
        assert validate_Hash(
            s.intersum, s.hash, s.currenttime.date()
        ), "个人积分校验失败，请联系管理员"
        assert s.intersum < kwargs["money"] * r.scale, "个人积分账户可兑换余额不足"

    # 检查个人现金账户
    try:
        m = AllinpayPlaceinterList.objects.get(
            pid=kwargs["pid"], sid=kwargs["sid"], intertype=1
        )
    except BaseException as err:
        m = AllinpayPlaceinterList(
            pid=kwargs["pid"],
            sid=kwargs["sid"],
            intertype=1,
            intersum=0,
            currenttime=timezone.now(),
        )
        m.save()
    else:
        assert validate_Hash(
            m.intersum, m.hash, m.currenttime.date()
        ), "个人现金账户校验失败，请联系管理员"

    # 事务处理积分和日志
    with transaction.atomic():
        t = timezone.now()
        # 扣积分
        ns = s.intersum - kwargs["money"] * r.scale
        s.intersum = ns
        s.hash = hasHashCode(ns, t.today().strftime("%Y-%m-%d"))
        s.currenttime = t
        s.save()
        # 加金额
        nm = m.intersum + kwargs["money"]
        m.intersum = nm
        m.hash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.currenttime = t
        if m.maxinter < nm:
            m.maxinter = nm
            m.maxhash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.save()
        # 写日志
        AllinpayPlaceinterLog(
            pid=kwargs["pid"],
            sid=kwargs["sid"],
            intertype=kwargs["intertype"],
            inter=kwargs["money"] * r.scale,
            intersum=ns,
            msgtype="积分兑换出账",
            # reqsn=reqsn,
            currenttime=t,
        ).save()
        AllinpayPlaceinterLog(
            pid=kwargs["pid"],
            sid=kwargs["sid"],
            intertype=1,
            inter=kwargs["money"],
            intersum=nm,
            msgtype="积分兑换入账",
            # reqsn=reqsn,
            currenttime=t,
        ).save()

    return "ok"


@shared_task
def ConvertInterAuto(*args, **kwargs):
    """自动兑换积分"""

    def checkOnDay(i):
        """检测兑换日期"""
        t = timezone.now()
        if i == 1:
            return True
        elif i == 2:
            if t.isoweekday() == 7:
                return True
            else:
                return False
        elif i == 3:
            if t.day == 1:
                return True
            else:
                return False
        elif i == 4:
            if t.month == 1 and t.day == 1:
                return True
            else:
                return False
        else:
            return False

    def maxConvert(i, r):
        """计算最大兑换金额"""
        x = math.floor(i / r)
        return x

    task = AllinpayPlaceinterConf.objects.filter(isauto=1).exclude(intetype=1)
    for i in task:
        if not checkOnDay(i.rate):
            continue
        sid = AllinpayPlacestaffList.objects.filter(pid=i.pid, status=1)
        for j in sid:
            try:
                pil = AllinpayPlaceinterList.objects.get(
                    pid=j.pid, sid=j.sid, intertype=i.intetype
                )
            except BaseException as err:
                # print(err)
                continue
            if pil.intersum < i.mixamount * i.scale:
                # print("积分余额不足")
                continue
            m = maxConvert(pil.intersum, i.scale)
            try:
                r = ConvertInterManual(
                    psid=j.id, intertype=i.intetype, money=m, pid=i.pid, sid=j.sid
                )
            except BaseException as err:
                # print(err)
                continue

    return {"rescode": 200, "resmsg": "OK"}


@shared_task
def Production_points(*args, **kwargs):
    """生产员工积分到账 \n
    场所ID, 员工ID, 原始单号, 积分类型(字符串), 积分类型(ID), 分值(int)\n
    # (1000001, 1005, 'CALL20230724163216QKS5PE', "呼叫积分", 2, types.le0,)\n
    """
    # print(args)
    # 检查个人现金账户
    try:
        m = AllinpayPlaceinterList.objects.get(
            pid=args[0], sid=args[1], intertype=args[4]
        )
    except BaseException as err:
        m = AllinpayPlaceinterList(
            pid=args[0],
            sid=args[1],
            intertype=args[4],
            intersum=0,
            maxinter=0,
            currenttime=timezone.now(),
        )
        m.save()
    # 事务处理积分和日志
    with transaction.atomic():
        t = timezone.now()
        # 加积分
        nm = m.intersum + args[5]
        m.intersum = nm
        m.hash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.currenttime = t
        if m.maxinter < nm:
            m.maxinter = nm
            m.maxhash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.save()
        # 写日志
        AllinpayPlaceinterLog(
            pid=args[0],
            sid=args[1],
            intertype=args[4],
            inter=args[5],
            intersum=nm,
            msgtype=args[3],
            reqsn=args[2],
            currenttime=t,
            status=0,
        ).save()
    return {"rescode": 200, "resmsg": "OK"}


@shared_task
def Membertion_points(*args, **kwargs):
    """生产会员积分到账"""
    # (1000001, 1005, 'CALL20230724163216QKS5PE', "呼叫积分", 2, types.le0,)
    # print(args)
    # 检查个人现金账户
    try:
        m = AllinpayMemberinterList.objects.get(
            pid=args[0], sid=args[1], intertype=args[4]
        )
    except BaseException as err:
        m = AllinpayMemberinterList(
            pid=args[0],
            sid=args[1],
            intertype=args[4],
            intersum=0,
            maxinter=0,
            currenttime=timezone.now(),
        )
        m.save()
    # 事务处理积分和日志
    with transaction.atomic():
        t = timezone.now()
        # 加积分
        nm = m.intersum + args[5]
        m.intersum = nm
        m.hash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.currenttime = t
        if m.maxinter < nm:
            m.maxinter = nm
            m.maxhash = hasHashCode(nm, t.today().strftime("%Y-%m-%d"))
        m.save()
        # 写日志
        AllinpayMemberinterLogs(
            pid=args[0],
            sid=args[1],
            intertype=args[4],
            inter=args[5],
            intersum=nm,
            msgtype=args[3],
            reqsn=args[2],
            currenttime=t,
            status=0,
        ).save()
    return {"rescode": 200, "resmsg": "OK"}


@shared_task
def RecordNationalIncentiveData(ShopReqsn, CallmeReqsn):
    """
    记录全民奖励
    ShopReqsn   string 商品订单号;
    CallmeReqsn string 派送订单号;
    """

    def has_staff(team):
        """查询团队成员"""
        try:
            r = AllinpayStaffteamList.objects.get(id=team)
        except BaseException as err:
            return []
        else:
            s = [int(x) for x in eval(r.staffs)]
            return s

    # 初始化数据
    d = timezone.now().date()
    try:
        s = FsygShopreqsnList.objects.get(reqsn=ShopReqsn)
        c = AllinpayCallmeList.objects.get(reqsn=CallmeReqsn)
        u = AllinpayStaffList.objects.get(id=c.target)
    except FsygShopreqsnList.DoesNotExist as err:
        return {"rescode": 400, "resmsg": "商品订单数据不存在"}
    except AllinpayCallmeList.DoesNotExist as err:
        return {"rescode": 400, "resmsg": "派送订单数据不存在"}
    except BaseException as err:
        return {"rescode": 400, "resmsg": "查找配送员工失败"}

    # 记录激励流水
    r = GIncentivesLog(
        **{
            "pid": c.pid,
            "sid": u.id,
            "money": int(float(s.amount) * 100),
            "status": 1,
            "reqsn": s.reqsn,
            "today": d,
            "nowtime": timezone.now(),
        }
    )
    r.save()

    # 查询全民激励对象
    Conf = GIncentivesConf.objects.filter(pid=c.pid)
    for i in Conf:
        if i.tid:
            # 团队成就计算
            staff = has_staff(i.tid)
            # 聚合查询成绩
            money = GIncentivesLog.objects.filter(
                pid=c.pid, sid__in=staff, today=d
            ).aggregate(Sum("money"))
            # 创建数据
            dbs = {"present": money, "status": 0}
            if money >= i.level1:
                dbs["finish1"] = timezone.now()
                dbs["status"] = 1
            if money >= i.level2:
                dbs["finish2"] = timezone.now()
                dbs["status"] = 2
            if money >= i.level3:
                dbs["finish3"] = timezone.now()
                dbs["status"] = 3

            # 更新到成就榜
            r, faq = GIncentivesList.objects.update_or_create(
                defaults=dbs, pid=c.pid, tid=i.tid, nowdate=d
            )
        else:
            # 个人成就计算
            # 聚合查询成绩
            money = GIncentivesLog.objects.filter(
                pid=c.pid, sid=u.id, today=d
            ).aggregate(Sum("money"))
            # 创建数据
            dbs = {"present": money, "status": 0}
            if i.level1 and i.level1 > 0 and money >= i.level1:
                dbs["finish1"] = timezone.now()
                dbs["status"] = 1
            if i.level2 and i.level2 > 0 and money >= i.level2:
                dbs["finish2"] = timezone.now()
                dbs["status"] = 2
            if i.level3 and i.level3 > 0 and money >= i.level3:
                dbs["finish3"] = timezone.now()
                dbs["status"] = 3

            # 更新到成就榜
            r, faq = GIncentivesList.objects.update_or_create(
                defaults=dbs, pid=c.pid, sid=u.id, nowdate=d
            )
    return {"rescode": 200, "resmsg": "OK"}
